/*                                                                     
 * Handling signals in a separate thread                         
 */                                                                   
#define _GNU_SOURCE                                                  
#define _REENTRANT                                                   
#include <pthread.h>                                                 
#include <iostream>                                                  
#include <csignal>                                                   
#include <cstdlib>                                                   
#include <unistd.h>     
                                             
using namespace std;                                                 

void *sibling(void *);                                          
void *thread_sig_handler(void *);                               

sigset_t global_sig_set;                                            
int global_parent_id;                                          

int main() {                                                             
  pthread_t t1, t2, t3;                                               
  sigfillset(&global_sig_set);                  // set of all signals
                                                // BLOCK all in set  
  pthread_sigmask(SIG_BLOCK, &global_sig_set, NULL);                 
                                                // Create 3 threads  
  pthread_create(&t1, NULL, thread_sig_handler, NULL);               
  pthread_create(&t2, NULL, sibling, NULL);                          
  pthread_create(&t3, NULL, sibling, NULL);                          

  global_parent_id = getpid();                                      

  while (1) {                                                         
    cout << "main thread \t PID: " << getpid() << " TID: "           
         <<  pthread_self() << endl;                                 
    sleep(3);                                                        
  }    
  
  return 0;                                                          
}  

void *sibling(void *arg) {                                                  
  while(1){                                                          
    cout << "sibling thread \t PID: " << getpid() << " TID: "        
         << pthread_self() << endl;                                  
    sleep(3);                                                        
  }                                                                  
  return NULL;                                                       
}                  

void *thread_sig_handler(void *arg) {                                      
  int sig;                                                          

  cout << "signal thread \t PID: " << getpid() << " TID: "           
       <<  pthread_self() << endl;                                   

  while(1){                                                          
    sigwait(&global_sig_set, &sig);                                
    if (sig == SIGINT) {                                            
      cout << "I am dead" << endl;                                   
      kill(global_parent_id, SIGKILL);                             
    }                                                                
    cout << endl << "signal " << sig << " caught by signal thread "  
         << pthread_self() << endl;                                  
  }   
  
  return NULL;                                                       
}                                                                    